import logging
import logging.handlers
import os
from pathlib import Path
import configparser
import flask

def request_id():
    headers = flask.request.headers
    request_id = headers.get("request_id")
    return request_id

class RequestIdFilter(logging.Filter):
    # This is a logging filter that makes the request ID available for use in
    # the logging format. Note that we're checking if we're in a request
    # context, as we may want to log things before Flask is fully loaded.
    def filter(self, record):
        record.request_id = request_id() if flask.has_request_context() else '-1'
        return True

class Logger:
    logger = None

    log_level = logging.INFO
    process_name = os.environ.get('API_SERVER_INFO', 'MainProcess')
    log_formatter = '%(levelname)s | %(asctime)s | {} | %(filename)s | [line:%(lineno)d] | request_id = %(request_id)s| %(message)s'.format(
        process_name)

    log_max_byte = 50 * 1024 * 1024
    log_backup_count = 5
    log_path = "logs"
    log_file_name = "running.log"

    @staticmethod
    def get_logger(logger_level=None):
        if Logger.logger is not None and logger_level is None:
            return Logger.logger

        log_fmt = logging.Formatter(Logger.log_formatter)
        filter = RequestIdFilter()
        # config file handler
        if not os.path.exists(Logger.log_path):
            os.makedirs(Logger.log_path)
        log_file = Logger.log_path + "/" + Logger.log_file_name
        if not os.path.exists(log_file):
            Path(log_file).touch()
        file_handler = logging.handlers.RotatingFileHandler(filename=log_file, maxBytes=Logger.log_max_byte,
                                                            backupCount=Logger.log_backup_count)
        file_handler.setFormatter(log_fmt)
        file_handler.addFilter(filter)

        # config console handler
        stream_handler = logging.StreamHandler()
        stream_handler.setFormatter(log_fmt)
        stream_handler.addFilter(filter)

        Logger.logger = logging.getLogger()
        if logger_level is not None:
            Logger.logger.setLevel(logger_level)
        else:
            Logger.logger.setLevel(Logger.log_level)
        Logger.logger.addHandler(file_handler)
        Logger.logger.addHandler(stream_handler)
        return Logger.logger


class ConfigLoader:
    def __init__(self, file):
        self.config_file = file
        self.config = configparser.ConfigParser()
        self._load_config()

    def _load_config(self):
        logger.info("loading config from file@{}".format(self.config_file))
        self.config.read(self.config_file)

    def get_config(self, section, option, default_cfg=None):
        cfg = default_cfg
        try:
            cfg = self.config.get(section, option)
        except configparser.NoSectionError:
            logger.error('section@{} not found!'.format(section))
        except configparser.NoOptionError:
            logger.error('option@{} not found in section@{}!'.format(option, section))
        except configparser.Error as e:
            logger.error('get config with ERROR@{}'.format(e))
        finally:
            return cfg


logger = Logger.get_logger()

# 配置
if os.environ.get('environment') == 'deploy' or os.environ.get('environment') == 'gpu':
    # product环境
    config_file = 'config/deploy/config.ini'
elif os.environ.get('environment') == 'fattest':
    config_file = 'config/fattest/config.ini'
elif os.environ.get('environment') == 'uat':
    config_file = 'config/uat/config.ini'
else:
    # 测试环境
    config_file = 'config/test/config.ini'
config = ConfigLoader(file=config_file)
